package com.imc.core.aop;

import com.imc.core.annotation.Logs;
import com.imc.core.utils.ExceptionUtil;
import com.twp.common.tuple.ResultDTO;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.security.Principal;
import java.util.Arrays;
import java.util.Optional;

/**
 * Created by tanweiping on 2018/7/27.
 */
/*
* 类描述：异常日志的打印的aop
* 开发者：tanweiping
* 创建日期：2018/8/7 09:59
*/
@Slf4j
@Aspect
@Order(0)
@Component
public class LogAop {

    @Pointcut("execution(* com..*.controller..*.add*(..))")
    public void addLog(){}

    @Pointcut("execution(* com..*.controller..*.update*(..))")
    public void updateLog(){}

    @Pointcut("execution(* com..*.controller..*.query*(..))")
    public void queryLog(){}

    @Pointcut("execution(* com..*.controller..*.del*(..))")
    public void delLog(){}

    @Pointcut("@annotation(com.imc.core.annotation.Logs)")
    public void WebLog(){}


    @Pointcut("addLog() || updateLog() || queryLog() || delLog() || WebLog()")
    public void log(){}

    /*
    * tanweiping  2018/8/7 10:16
    * 方法描述：记录日志的环绕处理
    */
    @Around(value = "log()")
    public Object around(ProceedingJoinPoint pjp) throws  Throwable{
        Object obj = null;
        boolean isLog = true;
        MethodSignature methodSignature = (MethodSignature)pjp.getSignature();
        Method method =  methodSignature.getMethod();

        Logs webLog = null;
        if (method.isAnnotationPresent(Logs.class)){
            webLog = method.getAnnotation(Logs.class);
            isLog = webLog.enable();
        }
        try {
           obj =  pjp.proceed();
        }catch (Exception e){
            if (isLog){
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                Principal principal = request.getUserPrincipal();
                Optional.ofNullable(
                        principal
                ).ifPresent(
                        p->log.error("loginName:"+principal.getName())
                );
                String message = ExceptionUtil.getRootCause(e).getMessage();
                String code = String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value());
                if (webLog!=null){
                    code = webLog.code();
                    if (StringUtils.isEmpty(message)){
                        message = webLog.label()+":"+message;
                    }
                }

                log.error("异常:"+ message);
                log.info("IP : " + request.getRemoteAddr());
                log.info("CLASS_METHOD : " + pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName());
                log.info("ARGS : " + Arrays.toString(pjp.getArgs()));
                //obj = ResultDTO.builder().isSuccess(false).message(message).code(code).build();
                Type t = method.getAnnotatedReturnType().getType();

                if (t == ResultDTO.class){
                    obj = ResultDTO.builder().isSuccess(false).message(message).code(code).build();
                }else {
                    obj = ((Class) t).newInstance();
                }
            }
        }
        return obj;
    }


}
